package com.xqboss.apps.service.user;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.domain.nft.Nft;
import com.xqboss.apps.domain.user.UserIdentity;
import com.xqboss.apps.domain.user.UserIdentityRank;
import com.xqboss.apps.dto.user.UserIdentitySaveDto;
import com.xqboss.apps.mapper.user.UserIdentityMapper;
import com.xqboss.apps.service.nft.NftService;
import com.xqboss.apps.vo.nft.BaseNftInfoVo;
import com.xqboss.apps.vo.user.UserIdentityDetailVo;
import com.xqboss.apps.vo.user.UserIdentitySimpleVo;
import com.xqboss.common.annotation.CacheRedis;
import com.xqboss.common.core.domain.TreeSelect;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.system.service.ISysUserService;
import com.xqboss.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户身份(UserIdentity)表服务实现类
 *
 * @author makejava
 * @since 2023-12-05 12:03:40
 */
@Service
public class UserIdentityService extends ServiceImpl<UserIdentityMapper, UserIdentity>  {

    @Autowired
    private UserIdentityRankService userIdentityRankService;

    @Autowired
    private NftService nftService;

    @Autowired
    private ISysUserService sysUserService;


    /**
     * 通过用户id获取当前身份
     * @param userId
     * @return
     */
    public UserIdentity getByUserId(Long userId) {
        Assert.notNull(userId,()->new ServiceException("用户id不能为空！"));
        SysUser user = sysUserService.selectUserById(userId);
        Assert.notNull(userId,()->new ServiceException("用户不存在！"));
        UserIdentityRank identityRank = userIdentityRankService.getById(user.getIdentityRankId());
        Assert.notNull(identityRank,()->new ServiceException("身份段位信息不存在！"));
        UserIdentity identity = this.getById(identityRank.getIdentityId());
        Assert.notNull(identity,()->new ServiceException("身份信息不存在！"));
        return identity;
    }

    /**
     * 列表
     * @return
     */
    public List<UserIdentitySimpleVo> simpleList() {
        List<UserIdentity> list = this.lambdaQuery().list();
        List<UserIdentitySimpleVo> voList = BeanUtil.copyToList(list, UserIdentitySimpleVo.class);
        UserIdentityRank rank;
        for (UserIdentitySimpleVo t : voList) {
            if(t.getId()==1){
                t.setIsEdit(Boolean.FALSE);
                t.setPreIdentityRankFullName("");
                continue;
            }
            rank = userIdentityRankService.lambdaQuery()
                    .eq(UserIdentityRank::getId, t.getPreIdentityRankId())
                    .eq(UserIdentityRank::getIsHighest, 1)
                    .one();
            t.setPreIdentityRankFullName(rank.getIdentityName() + (StringUtils.isBlank(rank.getName())?"":rank.getName()));
            t.setIsEdit(Boolean.TRUE);
        }
        return voList;
    }

    /**
     * 新增
     * @param param
     * @return
     */
    @Transactional(rollbackFor=Exception.class)
    public void add(UserIdentitySaveDto param) {
        checkValid(param);
        UserIdentity userIdentity = BeanUtil.copyProperties(param, UserIdentity.class);
        boolean result = this.save(userIdentity);
        if (!result) {
            throw new ServiceException("身份配置保存失败");
        }
        // 生成段位数据。根据最高段位
        List<UserIdentityRank> userIdentityRanks = new ArrayList<>();
        Integer highestRank = param.getHighestRank();
        if (highestRank == null) {
            highestRank = 1;
        }
        for (int i = 0; i < highestRank; i++) {
            UserIdentityRank userIdentityRank = new UserIdentityRank();
            userIdentityRank.setLevel(i + 1);
            userIdentityRank.setIdentityId(userIdentity.getId());
            userIdentityRank.setIdentityName(userIdentity.getName());
            if (param.getHighestRank() != null) {
                userIdentityRank.setName("lv." + userIdentityRank.getLevel());
            }
            if ((highestRank-1) == i) {
                userIdentityRank.setIsHighest(1);
            }
            userIdentityRanks.add(userIdentityRank);
        }
        result = userIdentityRankService.saveBatch(userIdentityRanks);
        if (!result) {
            throw new ServiceException("段位数据生成失败");
        }
    }

    /**
     * 修改
     * @param param
     */
    @Transactional(rollbackFor=Exception.class)
    public void edit(UserIdentitySaveDto param) {
        checkValid(param);
        if (param.getId() == null) {
            throw new ServiceException("id不能为空");
        }
        UserIdentity old = this.getById(param.getId());
        if (old == null) {
            throw new ServiceException("身份配置不存在");
        }
        if (!Objects.equals(old.getHighestRank(), param.getHighestRank())) {
            throw new ServiceException("最高段位不可修改");
        }
        UserIdentity userIdentity = BeanUtil.copyProperties(param, UserIdentity.class);
        boolean result = this.updateById(userIdentity);
        if (!result) {
            throw new ServiceException("身份配置保存失败");
        }
        if (!old.getName().equals(userIdentity.getName())) {
            // 批量修改段位中的身份名称
            result = userIdentityRankService.lambdaUpdate()
                    .eq(UserIdentityRank::getIdentityId, userIdentity.getId())
                    .set(UserIdentityRank::getIdentityName, userIdentity.getName())
                    .set(UserIdentityRank::getUpdateTime, new Date())
                    .update();
            if (!result) {
                throw new ServiceException("段位数据更新失败");
            }
        }
    }


    /**
     * 详情
     * @param id
     */
    public UserIdentityDetailVo info(Long id) {
        UserIdentity userIdentity = this.getById(id);
        if (userIdentity == null) {
            throw new ServiceException("身份配置不存在");
        }
        UserIdentityDetailVo vo = BeanUtil.copyProperties(userIdentity, UserIdentityDetailVo.class);
        if (vo.getIdentityCardNftId() != null) {
            Nft identityCardNft = nftService.getNft(vo.getIdentityCardNftId());
            BaseNftInfoVo baseNftVo = new BaseNftInfoVo();
            baseNftVo.setMainImg(identityCardNft.getMainImg());
            baseNftVo.setTitle(identityCardNft.getTitle());
            vo.setIdentityCardNft(baseNftVo);
        }
        if (vo.getFragmentNftId() != null) {
            Nft identityCardNft = nftService.getNft(vo.getFragmentNftId());
            BaseNftInfoVo baseNftVo = new BaseNftInfoVo();
            baseNftVo.setMainImg(identityCardNft.getMainImg());
            baseNftVo.setTitle(identityCardNft.getTitle());
            vo.setFragmentNft(baseNftVo);
        }
        return vo;
    }


    /**
     * 检查有效性
     * @param param
     */
    private void checkValid(UserIdentitySaveDto param) {
        if (param.getIsFragments() == 0 && param.getIsIdentityCard() == 0) {
            throw new ServiceException("身份卡和碎片至少选择一种");
        } else if (param.getIsFragments() == 1 && param.getHighestRank() == null) {
            throw new ServiceException("最高段位为空时，不能选择碎片升级");
        }
        if (param.getIsIdentityCard() == 1) {
            if (param.getIdentityCardNftId() == null) {
                throw new ServiceException("身份卡藏品不能为空");
            }
            if (param.getIdentityCardIntegralCost() == null) {
                throw new ServiceException("身份卡消耗热豆数量不能为空");
            }
        } else {
            param.setIdentityCardNftId(null);
            param.setIdentityCardIntegralCost(null);
        }
        if (param.getIsFragments() == 1) {
            if (param.getFragmentNftId() == null) {
                throw new ServiceException("碎片藏品不能为空");
            }
            if (param.getFragmentIntegralCost() == null) {
                throw new ServiceException("碎片消耗热豆数量不能为空");
            }
            if (param.getFragmentIntegralCostFactor() == null) {
                throw new ServiceException("碎片热豆消耗系数不能为空");
            }
        } else {
            param.setFragmentNftId(null);
            param.setFragmentIntegralCost(null);
            param.setFragmentIntegralCostFactor(null);
        }
        if (param.getIsIdentityCard() == 1 && param.getIsFragments() == 1 && param.getIdentityCardNftId() == param.getFragmentNftId()) {
            throw new ServiceException("两个升段方案的藏品Id不能相同");
        }
        if (this.lambdaQuery()
                .eq(UserIdentity::getPreIdentityRankId, param.getPreIdentityRankId())
                .ne(param.getId() != null, UserIdentity::getId, param.getId()).count()>0) {
            throw new ServiceException("当前身份前置身份段位已存在！");
        }
        if (this.lambdaQuery()
                .eq(UserIdentity::getName, param.getName())
                .ne(param.getId() != null, UserIdentity::getId, param.getId()).count()>0) {
            throw new ServiceException("该身份名称已存在！");
        }

    }


    /**
     * 树形列表
     * @return
     */
    public List<TreeSelect> treeList() {
        List<UserIdentityRank> list = userIdentityRankService.lambdaQuery().orderByAsc(UserIdentityRank::getId).list();
        // 根据身份id分组，
        String splitChar = "-";
        Map<String, List<UserIdentityRank>> map =  list.stream().collect(Collectors.groupingBy(t -> t.getIdentityId() + splitChar + t.getIdentityName()));
        List<TreeSelect> treeSelects = new ArrayList<>();
        map.forEach((k,v) -> {
            TreeSelect treeSelect = new TreeSelect();
            treeSelect.setId(Long.valueOf(k.split(splitChar)[0]));
            treeSelect.setLabel(k.split(splitChar)[1]);
            List<TreeSelect> children = new ArrayList<>();
            // 如果子对象的长度为1且label是空，则表示没有段位，需要把子id设置为父id
            if (v.size() == 1 && StringUtils.isBlank(v.get(0).getName())) {
                treeSelect.setId(v.get(0).getId());
                treeSelect.setLabel(v.get(0).getIdentityName());
                treeSelects.add(treeSelect);
            } else {
                v.forEach(t -> {
                    TreeSelect child = new TreeSelect();
                    child.setId(t.getId());
                    child.setLabel(t.getName());
                    children.add(child);
                });
                treeSelect.setChildren(children);
                treeSelects.add(treeSelect);
            }
        });
        treeSelects.sort(Comparator.comparing(TreeSelect::getId));
        return treeSelects;
    }

    /**
     * 根据 身份段位id 获取下一级身份
     *
     * @param identityRankId 身份段位id
     * @return 身份信息
     */
    public UserIdentity getNextIdentity(Long identityRankId) {
        LambdaQueryWrapper<UserIdentity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserIdentity::getPreIdentityRankId,identityRankId);
        return this.getOne(wrapper);
    }

    /**
     * 检测是否大于等于
     * @param sourceIdentityId
     * @param targetIdentityId
     * @return
     */
    @CacheRedis(expireTime = 60)
    public boolean checkGE(Long sourceIdentityId, Long targetIdentityId) {
        if (Objects.equals(sourceIdentityId, targetIdentityId)) {
            return true;
        }
        UserIdentity sourceIdentity = this.getById(sourceIdentityId);
        UserIdentity targetIdentity = this.getById(targetIdentityId);
        if (sourceIdentity == null || targetIdentity == null) {
            throw new ServiceException("身份不存在");
        }
        if (sourceIdentity.getPreIdentityRankId() == null || sourceIdentity.getPreIdentityRankId() == 0L) {
            return false;
        }
        return checkGE(userIdentityRankService.getById(sourceIdentity.getPreIdentityRankId()).getIdentityId(), targetIdentityId);
    }
}

